package com.yum.Iterator.Map.YAbstractMap.HashMap;

import com.yum.Iterator.Map.YMap;

/**
 * Created on 2023/6/11
 *
 * @Time 20:36
 * @Program YunMap
 * @Author YoHaNe/XiaoShuai
 */
public class YLinkedHashMap<K,V> extends YHashMap<K,V> implements YMap<K,V> {
    private static final long serialVersionUID = -9129341721915963037L;

    transient YLinkedHashMap.YEntry<K,V> head;

    transient YLinkedHashMap.YEntry<K,V> tail;

    /**
     * true:顺序排序
     * false:插入顺序排序 (默认)
     */
    final boolean accessOrder;

    public YLinkedHashMap(){
        super();
        accessOrder = false;
    }

    public YLinkedHashMap(int initialCapacity){
        super(initialCapacity);
        accessOrder = false;
    }

    public YLinkedHashMap(int initCapacity, float loadFactor) {
        super(initCapacity, loadFactor);
        this.accessOrder = false;
    }

    static class YEntry<K,V> extends YHashMap.YNode<K,V>{
        YEntry<K,V> before,after;
        YEntry(int hash,K key,V value,YNode<K,V> next){
            super(hash, key, value, next);
        }
    }

    /**
     * 在节点被访问后根据accessOrder判断是否调整链表顺序
     * @param p
     */
    @Override
    void afterNodeAccess(YNode<K, V> p) {
        YLinkedHashMap.YEntry<K,V> last;
        if(accessOrder && (last = tail) != p){
            //e:当前节点 a:后一个节点 b:前一个节点
            //现在的结构 b <=> p <=> a
            YLinkedHashMap.YEntry<K,V> e = (YEntry<K, V>) p,b = e.before,a = e.after;
            //b <=> p <- a
            e.after = null;
            //若当前节点p是头节点,则头节点改为a
            if(b == null)
                head = a;
            //若不是,则把前后节点连接
            //b -> a
            else
                b.after = a;
            //若a不为空则 b <- a
            if(a != null)
                a.before = b;
            else
                last = b;
            //若是空链表则e为头节点
            if(last == null)
                head = e;
            else {
                e.before = last;
                last.after = e;
            }
            tail = e;
            ++modCount;
        }
    }

    @Override
    void afterNodeInsertion(boolean evict) {
        YLinkedHashMap.YEntry<K,V> first;
        if(evict && (first = head) != null && removeEldesEntry(first)){
            K key = first.key;
            removeNode(hashCode(key),key,null,false,true);
        }
    }

    /**
     * 删除后处理其对应链表前后关系
     * @param p
     */
    @Override
    void afterNodeRemoval(YNode<K, V> p) {
        YLinkedHashMap.YEntry<K,V> e = (YEntry<K, V>) p,b = e.before,a = e.after;
        e.before = e.after = null;
        if(b == null)
            head = a;
        else
            a.before = b;
    }

    /**
     * 此方法在此是无任何意义
     * 等待程序员重写
     */
    protected boolean removeEldesEntry(YMap.YEntry<K,V> eldest){
        return false;
    }
}
